package com.gopay.checkorder.service.proxy;

import com.gopay.checkorder.manager.BankOrderManager;
import com.gopay.checkorder.service.BankOrderService;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankOrderLock;
import com.gopay.common.constants.bank.BankOrderStatus;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.cps.manager.order.CpsGeneralMainOrderQueryManager;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.CheckOrderLog;
import com.gopay.common.domain.bank.dayend.BaseDayendEntry;
import com.gopay.common.domain.cps.vo.CheckOrderResult;
import com.gopay.common.exception.GopayException;
import com.gopay.common.trace.anotation.GopayTracer;
import com.gopay.common.util.spring.SpringContextUtil;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * Created by zyt on 2017/8/4.
 * 单独对自动结算银企直联代理业务，不通知cashier做账
 */
@Service("bcdlCheckOrderProxy")
public class BcdlCheckOrderProxy implements BankOrderService {
    private final static Logger logger = LoggerFactory.getLogger(BcdlCheckOrderProxy.class);

    @Resource(name = "bankOrderManager")
    protected BankOrderManager bankOrderManager;

    @Resource(name = "cpsGeneralMainOrderQueryManager")
    protected CpsGeneralMainOrderQueryManager mainOrderQuery;



    @Override
    @GopayTracer(orderIdSpel = "#bankOrder.orderId")
    public CheckOrderResult checkOrder(BankOrder bankOrder, String bankOrderStatus) {
        CheckOrderResult checkOrderResult = new CheckOrderResult(false);
        if (bankOrder == null || StringUtils.isBlank(bankOrder.getOrderId())) {
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5060);
            checkOrderResult.setErrMsg("银行订单不存在");
            logger.error("bankOrder is null or orderId is null.");
            return checkOrderResult;
        }
        
        checkOrderResult.setOrderId(bankOrder.getOrderId());
        
        //只接收09（银企直联）的订单请求
        if (!StringUtils.equals(bankOrder.getBankBizProdCode(), BisBankBusinessProd._09.value)) {
            logger.error("注意!!!银行业务产品码不匹配，此订单银行业务产品码 = " + bankOrder.getBankBizProdCode() + ",正确的银行业务产品码 "
                    + BisBankBusinessProd._09.value);
            //todo   需重新定义错误码
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5035);
            checkOrderResult.setErrMsg("银行业务产品码不匹配");
            return checkOrderResult;
        }
        
        //判断当前bankOrder的锁定状态，如果锁定，则返回，防止高并发的时候，出现重复调用问题
        if(bankOrder.getLock() == BankOrderLock.LOCK){
            //todo，需要重新定义错误码
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5042);
            checkOrderResult.setErrMsg("订单状态异常，bankOrder已经锁定");
            return checkOrderResult;
        }
        try {
            // 锁定银行流水记录
            if (bankOrderManager.lock(bankOrder) == 0) {
                logger.error("BcdlCheckOrderProxy lock bankMainOrder failed: orderId " + bankOrder.getOrderId());
                checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5095);
                checkOrderResult.setErrMsg("bankOrder锁定失败");
                return checkOrderResult;
            }
            // 自动发起对单时,对单次数+1(状态不等于'入账失败')
            if (StringUtils.equals(BankOrderStatus.AUTO_CHECK_SUCCESS, bankOrderStatus)
                    && !StringUtils.equals(BankOrderStatus.ENTER_ACCOUNT_FIAL, bankOrder.getOrderStatus())) {
                bankOrderManager.updateTotalCheckTimes(bankOrder);
            }

            logger.error(bankOrder.getOrderId() + " BcdlCheckOrderProxy totalchecktimes: " + bankOrder.getTotalCheckTimes());

            // 继续对账
            String beanName = getBeanName(bankOrder.getBankBizProdCode(), bankOrder.getBankCode());
            if(BisBankInterfaceChannel._18.value.equals(bankOrder.getInterfaceChennelCode())){
                // 网联付款渠道
                beanName = "NUCCPAY-BCDL";
            }
            if (false == SpringContextUtil.containsBean(beanName)) {
                logger.error("spring bean does not exist: " + beanName);
                checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6044);
                return checkOrderResult;
            }

            BankOrderService checkOrderService = (BankOrderService) SpringContextUtil.getBean(beanName);
            checkOrderResult = checkOrderService.checkOrder(bankOrder, bankOrderStatus);
            /**
             * 测试成功
             */
//            checkOrderResult.setSuccess(true);
//            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100S1000);
            /**
             * 测试失败
             */
            /*checkOrderResult.setSuccess(false);
            checkOrderResult.setBankFailure(true);
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6027);*/
            logger.error("bcdl checkOrderResult: " + ToStringBuilder.reflectionToString(checkOrderResult));


            if (checkOrderResult.isSuccess()) {
                logger.info("bank orderid: " + bankOrder.getOrderId() + ",银行对账成功");
                // 对单成功，未做账
                bankOrderManager.updateSuccess(bankOrder, bankOrderStatus);
                checkOrderResult.setSuccess(true);
                logger.error("bank orderid: " + bankOrder.getOrderId() + ",bcdl check order success,waitting for doing Acct!!");
            } else if (checkOrderResult.isBankFailure()) {
                // 银行订单失败
                checkOrderResult.setSuccess(false);
                logger.error("bank orderid: " + bankOrder.getOrderId() + ",bcdl bank return failure,waitting for doing Acct!!!");
                // 对单失败,状态更新99
                bankOrderManager.updateFail(bankOrder);
                return checkOrderResult;
            }

        } catch (Exception e) {
            logger.error(bankOrder.getOrderId() + "bcdl checkOrder error message: ", e);
        } finally {
            // 解锁
            bankOrderManager.unlock(bankOrder);
        }

        updateCheckAcctLog(bankOrder, checkOrderResult, bankOrderStatus);

        return checkOrderResult;
    }

    private String getBeanName(String bankBusProd, String bankCode) throws GopayException {
        String beanName = "";
        if (StringUtils.equals(BisBankBusinessProd._09.value, bankBusProd)) {
            beanName = bankCode + "-BCDL";
        }
        return beanName;
    }

    /**
     *  更新自动对账日志记录表
     * @param bankOrder
     * @param checkOrderResult
     * @param target
     */
    private void updateCheckAcctLog(BankOrder bankOrder, CheckOrderResult checkOrderResult, String target){
        try {
            // 更新自动对账日志记录表
            CheckOrderLog checkOrderLog = new CheckOrderLog();
            checkOrderLog.setOutOrderId(bankOrder.getOutOrderId());
            if (checkOrderResult.isSuccess()) {
                checkOrderLog.setIsCheckOk(1);
                // 对账成功赋值errcode，为日志记录做准备
                checkOrderResult.setErrCode("SUCCESS");
            }
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
            Date date;
            date = format.parse(format.format(new Date()));
            // 自动发起对单时,对单次数+1(状态不等于'入账失败')
            if (StringUtils.equals(BankOrderStatus.AUTO_CHECK_SUCCESS, target)
                    && !StringUtils.equals(BankOrderStatus.ENTER_ACCOUNT_FIAL, bankOrder.getOrderStatus())) {
                if (bankOrder.getTotalCheckTimes() > 0) {
                    if (bankOrder.getTotalCheckTimes() == 1) {
                        checkOrderLog.setRespcode(checkOrderResult.getErrCode());
                        checkOrderLog.setChecktime(date);
                        checkOrderLog.setCheckCount(bankOrder.getTotalCheckTimes());
                        bankOrderManager.insertCheckOrderLog(checkOrderLog);
                        logger.error("新增完成checkOrderLog日志表");
                    } else {
                        bankOrderManager.updateCheckOrderLog(checkOrderLog, checkOrderResult.getErrCode(), date,
                                bankOrder.getTotalCheckTimes());
                        logger.error("更新完成checkOrderLog日志表");
                    }
                }
            }
        } catch (Exception e) {
            logger.error("checkOrder updateLog error.", e);
        }
    }

    @Override
    public BankOrder getDbOrder() {
        return null;
    }

    @Override
    public BaseMessage dayend(String bank_bus) {
        return null;
    }

    @Override
    public Result getDayendMsg(String string) {
        return null;
    }

    @Override
    public List<CheckOrderResult> checkDayend(String bank_bus) {
        return null;
    }

    @Override
    public CheckOrderResult checkDayendOrder(BaseDayendEntry bdm, BankOrder bo) {
        return null;
    }

}
